home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / gnu / uucp-104.lha / uucp-1.04 / uuconf / vsinfo.c < prev    next >
C/C++ Source or Header  |  1993-02-13  |  15KB  |  576 lines

  1. /* vsinfo.c
  2.    Get information about a system from the V2 configuration files.
  3.  
  4.    Copyright (C) 1992 Ian Lance Taylor
  5.  
  6.    This file is part of the Taylor UUCP uuconf library.
  7.  
  8.    This library is free software; you can redistribute it and/or
  9.    modify it under the terms of the GNU Library General Public License
  10.    as published by the Free Software Foundation; either version 2 of
  11.    the License, or (at your option) any later version.
  12.  
  13.    This library is distributed in the hope that it will be useful, but
  14.    WITHOUT ANY WARRANTY; without even the implied warranty of
  15.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.    Library General Public License for more details.
  17.  
  18.    You should have received a copy of the GNU Library General Public
  19.    License along with this library; if not, write to the Free Software
  20.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  
  22.    The author of the program may be contacted at ian@airs.com or
  23.    c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
  24.    */
  25.  
  26. #include "uucnfi.h"
  27.  
  28. #if USE_RCS_ID
  29. const char _uuconf_vsinfo_rcsid[] = "$Id: vsinfo.c,v 1.4 1992/07/25 20:44:25 ian Rel $";
  30. #endif
  31.  
  32. #include <errno.h>
  33. #include <ctype.h>
  34.  
  35. /* Get the information for a particular system from the V2
  36.    configuration files.  This does not make sure that all the default
  37.    values are set.  */
  38.  
  39. int
  40. _uuconf_iv2_system_internal (qglobal, zsystem, qsys)
  41.      struct sglobal *qglobal;
  42.      const char *zsystem;
  43.      struct uuconf_system *qsys;
  44. {
  45.   char *zline;
  46.   size_t cline;
  47.   char **pzsplit;
  48.   size_t csplit;
  49.   char **pzcomma;
  50.   size_t ccomma;
  51.   FILE *e;
  52.   int cchars;
  53.   pointer pblock;
  54.   int iret;
  55.  
  56.   e = fopen (qglobal->qprocess->zv2systems, "r");
  57.   if (e == NULL)
  58.     {
  59.       if (FNO_SUCH_FILE ())
  60.     return UUCONF_NOT_FOUND;
  61.       qglobal->ierrno = errno;
  62.       qglobal->zfilename = qglobal->qprocess->zv2systems;
  63.       return (UUCONF_FOPEN_FAILED
  64.           | UUCONF_ERROR_ERRNO
  65.           | UUCONF_ERROR_FILENAME);
  66.     }
  67.  
  68.   zline = NULL;
  69.   cline = 0;
  70.   pzsplit = NULL;
  71.   csplit = 0;
  72.   pzcomma = NULL;
  73.   ccomma = 0;
  74.  
  75.   pblock = NULL;
  76.   iret = UUCONF_SUCCESS;
  77.  
  78.   qglobal->ilineno = 0;
  79.  
  80.   while ((cchars = getline (&zline, &cline, e)) > 0)
  81.     {
  82.       int ctoks, ctimes, i;
  83.       struct uuconf_system *qset;
  84.       char *z, *zretry;
  85.       int cretry;
  86.  
  87.       ++qglobal->ilineno;
  88.  
  89.       --cchars;
  90.       if (zline[cchars] == '\n')
  91.     zline[cchars] = '\0';
  92.       zline[strcspn (zline, "#")] = '\0';
  93.  
  94.       ctoks = _uuconf_istrsplit (zline, '\0', &pzsplit, &csplit);
  95.       if (ctoks < 0)
  96.     {
  97.       qglobal->ierrno = errno;
  98.       iret = UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO;
  99.       break;
  100.     }
  101.  
  102.       /* If this isn't the system we're looking for, keep reading
  103.      the file.  */
  104.       if (ctoks < 1
  105.       || strcmp (zsystem, pzsplit[0]) != 0)
  106.     continue;
  107.  
  108.       /* If this is the first time we've found the system, we want
  109.      to set *qsys directly.  Otherwise, we allocate a new
  110.      alternate.  */
  111.       if (pblock == NULL)
  112.     {
  113.       pblock = uuconf_malloc_block ();
  114.       if (pblock == NULL)
  115.         {
  116.           qglobal->ierrno = errno;
  117.           iret = UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO;
  118.           break;
  119.         }
  120.       _uuconf_uclear_system (qsys);
  121.       qsys->uuconf_palloc = pblock;
  122.       qset = qsys;
  123.     }
  124.       else
  125.     {
  126.       struct uuconf_system **pq;
  127.  
  128.       qset = ((struct uuconf_system *)
  129.           uuconf_malloc (pblock, sizeof (struct uuconf_system)));
  130.       if (qset == NULL)
  131.         {
  132.           qglobal->ierrno = errno;
  133.           iret = UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO;
  134.           break;
  135.         }
  136.       _uuconf_uclear_system (qset);
  137.       for (pq = &qsys->uuconf_qalternate;
  138.            *pq != NULL;
  139.            pq = &(*pq)->uuconf_qalternate)
  140.         ;
  141.       *pq = qset;
  142.     }
  143.  
  144.       /* Add this line to the memory block we are building for the
  145.      system.  */
  146.       if (uuconf_add_block (pblock, zline) != 0)
  147.     {
  148.       qglobal->ierrno = errno;
  149.       iret = UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO;
  150.       break;
  151.     }
  152.  
  153.       zline = NULL;
  154.       cline = 0;
  155.  
  156.       /* The format of a line in Systems is
  157.      system time device speed phone chat
  158.      For example,
  159.      airs Any ACU 9600 5551212 ogin: foo pass: bar
  160.      */
  161.  
  162.       /* Get the system name.  */
  163.  
  164.       qset->uuconf_zname = pzsplit[0];
  165.       qset->uuconf_fcall = TRUE;
  166.       qset->uuconf_fcalled = TRUE;
  167.  
  168.       if (ctoks < 2)
  169.     continue;
  170.  
  171.       /* A time string is "time/grade,time/grade;retry".  A missing
  172.      grade is taken as BGRADE_LOW.  On some versions the retry
  173.      time is actually separated by a comma, which won't work right
  174.      here.  */
  175.       zretry = strchr (pzsplit[1], ';');
  176.       if (zretry == NULL)
  177.     cretry = 0;
  178.       else
  179.     {
  180.       *zretry = '\0';
  181.       cretry = (int) strtol (zretry + 1, (char **) NULL, 10);
  182.     }
  183.  
  184.       ctimes = _uuconf_istrsplit (pzsplit[1], ',', &pzcomma, &ccomma);
  185.       if (ctimes < 0)
  186.     {
  187.       qglobal->ierrno = errno;
  188.       iret = UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO;
  189.       break;
  190.     }
  191.  
  192.       for (i = 0; i < ctimes; i++)
  193.     {
  194.       char *zslash;
  195.       char bgrade;
  196.  
  197.       z = pzcomma[i];
  198.       zslash = strchr (z, '/');
  199.       if (zslash == NULL)
  200.         bgrade = UUCONF_GRADE_LOW;
  201.       else
  202.         {
  203.           *zslash = '\0';
  204.           bgrade = zslash[1];
  205.           if (! UUCONF_GRADE_LEGAL (bgrade))
  206.         bgrade = UUCONF_GRADE_LOW;
  207.         }
  208.  
  209.       iret = _uuconf_itime_parse (qglobal, z, (long) bgrade, cretry,
  210.                       _uuconf_itime_grade_cmp,
  211.                       &qset->uuconf_qtimegrade,
  212.                       pblock);
  213.       if (iret != UUCONF_SUCCESS)
  214.         break;
  215.     }
  216.  
  217.       if (iret != UUCONF_SUCCESS)
  218.     break;
  219.  
  220.       if (ctoks < 3)
  221.     continue;
  222.  
  223.       /* Pick up the device name.  It can be followed by a comma and a
  224.      list of protocols (this is not actually supported by most V2
  225.      systems, but it should be compatible).  */
  226.       qset->uuconf_zport = pzsplit[2];
  227.       z = strchr (pzsplit[2], ',');
  228.       if (z != NULL)
  229.     {
  230.       qset->uuconf_zprotocols = z + 1;
  231.       *z = '\0';
  232.     }
  233.  
  234.       /* If the port is "TCP", we set up a system specific port.  The
  235.      baud rate becomes the service number and the phone number
  236.      becomes the address (still stored in qsys->zphone).  */
  237.       if (strcmp (qset->uuconf_zport, "TCP") == 0)
  238.     {
  239.       qset->uuconf_zport = NULL;
  240.       qset->uuconf_qport = ((struct uuconf_port *)
  241.                 uuconf_malloc (pblock,
  242.                            sizeof (struct uuconf_port)));
  243.       if (qset->uuconf_qport == NULL)
  244.         {
  245.           qglobal->ierrno = errno;
  246.           iret = UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO;
  247.           break;
  248.         }
  249.       _uuconf_uclear_port (qset->uuconf_qport);
  250.       qset->uuconf_qport->uuconf_zname = (char *) "TCP";
  251.       qset->uuconf_qport->uuconf_ttype = UUCONF_PORTTYPE_TCP;
  252.       qset->uuconf_qport->uuconf_ireliable
  253.         = (UUCONF_RELIABLE_ENDTOEND | UUCONF_RELIABLE_RELIABLE
  254.            | UUCONF_RELIABLE_EIGHT | UUCONF_RELIABLE_FULLDUPLEX
  255.            | UUCONF_RELIABLE_SPECIFIED);
  256.       if (ctoks < 4)
  257.         qset->uuconf_qport->uuconf_u.uuconf_stcp.uuconf_zport
  258.           = (char *) "uucp";
  259.       else
  260.         qset->uuconf_qport->uuconf_u.uuconf_stcp.uuconf_zport
  261.           = pzsplit[3];
  262.     }
  263.  
  264.       if (ctoks < 4)
  265.     continue;
  266.  
  267.       qset->uuconf_ibaud = strtol (pzsplit[3], (char **) NULL, 10);
  268.  
  269.       if (ctoks < 5)
  270.     continue;
  271.  
  272.       /* Get the phone number.  */
  273.       qset->uuconf_zphone = pzsplit[4];
  274.  
  275.       if (ctoks < 6)
  276.     continue;
  277.  
  278.       /* Get the chat script.  We just hand this off to the chat
  279.      script processor, so that it will parse subsend and
  280.      subexpect strings correctly.  */
  281.       pzsplit[4] = (char *) "chat";
  282.       iret = _uuconf_ichat_cmd (qglobal, ctoks - 4, pzsplit + 4,
  283.                 &qset->uuconf_schat, pblock);
  284.       iret &=~ UUCONF_CMDTABRET_KEEP;
  285.       if (iret != UUCONF_SUCCESS)
  286.     break;
  287.     }
  288.  
  289.   (void) fclose (e);
  290.  
  291.   if (pzcomma != NULL)
  292.     free ((pointer) pzcomma);
  293.  
  294.   if (iret != UUCONF_SUCCESS)
  295.     {
  296.       if (zline != NULL)
  297.     free ((pointer) zline);
  298.       if (pzsplit != NULL)
  299.     free ((pointer) pzsplit);
  300.       qglobal->zfilename = qglobal->qprocess->zv2systems;
  301.       return iret | UUCONF_ERROR_FILENAME | UUCONF_ERROR_LINENO;
  302.     }
  303.  
  304.   if (pblock == NULL)
  305.     {
  306.       if (zline != NULL)
  307.     free ((pointer) zline);
  308.       if (pzsplit != NULL)
  309.     free ((pointer) pzsplit);
  310.       return UUCONF_NOT_FOUND;
  311.     }
  312.  
  313.   /* Now read USERFILE and L.cmds to get permissions.  We can't fully
  314.      handle USERFILE since that specifies permissions based on local
  315.      users which we do not support.  */
  316.   {
  317.     e = fopen (qglobal->qprocess->zv2userfile, "r");
  318.     if (e != NULL)
  319.       {
  320.     char **pzlocal, **pzremote;
  321.     boolean fdefault_callback;
  322.     char *zdefault_login;
  323.     struct uuconf_system *q;
  324.  
  325.     pzlocal = NULL;
  326.     pzremote = NULL;
  327.     fdefault_callback = FALSE;
  328.     zdefault_login = NULL;
  329.  
  330.     qglobal->ilineno = 0;
  331.  
  332.     while ((cchars = getline (&zline, &cline, e)) > 0)
  333.       {
  334.         int ctoks;
  335.         char *zcomma;
  336.         boolean fcallback;
  337.         char **pzlist, **pznew;
  338.  
  339.         ++qglobal->ilineno;
  340.  
  341.         --cchars;
  342.         if (zline[cchars] == '\n')
  343.           zline[cchars] = '\0';
  344.         zline[strcspn (zline, "#")] = '\0';
  345.  
  346.         ctoks = _uuconf_istrsplit (zline, '\0', &pzsplit, &csplit);
  347.         if (ctoks < 0)
  348.           {
  349.         qglobal->ierrno = errno;
  350.         iret = UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO;
  351.         break;
  352.           }
  353.  
  354.         if (ctoks == 0)
  355.           continue;
  356.  
  357.         /* The first field is username,machinename */
  358.         zcomma = strchr (pzsplit[0], ',');
  359.         if (zcomma == NULL)
  360.           continue;
  361.  
  362.         *zcomma++ = '\0';
  363.  
  364.         /* The rest of the line is the list of directories, except
  365.            that if the first directory is "c" we must call the
  366.            system back.  */
  367.         fcallback = FALSE;
  368.         pzlist = pzsplit + 1;
  369.         --ctoks;
  370.         if (ctoks > 0
  371.         && pzsplit[1][0] == 'c'
  372.         && pzsplit[1][1] == '\0')
  373.           {
  374.         fcallback = TRUE;
  375.         pzlist = pzsplit + 2;
  376.         --ctoks;
  377.           }
  378.  
  379.         /* Now pzsplit[0] is the user name, zcomma is the system
  380.            name, fcallback indicates whether a call back is
  381.            required, ctoks is the number of directories and pzlist
  382.            points to the directories.  If the system name matches,
  383.            then the user name is the name that the system must use
  384.            to log in, and the list of directories is what may be
  385.            transferred in by either local or remote request.
  386.            Otherwise, if no system name matches, then the first
  387.            line with no user name gives the list of directories
  388.            that may be transferred by local request, and the first
  389.            line with no system name gives the list of directories
  390.            that may be transferred by remote request.  */
  391.         if ((pzsplit[0][0] != '\0' || pzlocal != NULL)
  392.         && (zcomma[0] != '\0' || pzremote != NULL)
  393.         && strcmp (zcomma, zsystem) != 0)
  394.           continue;
  395.  
  396.         /* NULL terminate the list of directories.  */
  397.         pznew = (char **) uuconf_malloc (pblock,
  398.                           (ctoks + 1) * sizeof (char *));
  399.         if (pznew == NULL)
  400.           {
  401.         qglobal->ierrno = errno;
  402.         iret = UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO;
  403.         break;
  404.           }
  405.         memcpy ((pointer) pznew, (pointer) pzlist,
  406.             ctoks * sizeof (char *));
  407.         pznew[ctoks] = NULL;
  408.  
  409.         if (uuconf_add_block (pblock, zline) != 0)
  410.           {
  411.         qglobal->ierrno = errno;
  412.         iret = UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO;
  413.         break;
  414.           }
  415.         zline = NULL;
  416.         cline = 0;
  417.  
  418.         if (pzsplit[0][0] == '\0')
  419.           {
  420.         pzlocal = pznew;
  421.         fdefault_callback = fcallback;
  422.           }
  423.         else if (zcomma[0] == '\0')
  424.           {
  425.         pzremote = pznew;
  426.         zdefault_login = pzsplit[0];
  427.           }
  428.         else
  429.           {
  430.         /* Both the login name and the machine name were
  431.            listed; require the machine to be logged in under
  432.            this name.  This is not fully backward compatible,
  433.            and perhaps should be changed.  On the other hand,
  434.            it is more useful.  */
  435.         for (q = qsys; q != NULL; q = q->uuconf_qalternate)
  436.           {
  437.             q->uuconf_zcalled_login = pzsplit[0];
  438.             q->uuconf_fcallback = fcallback;
  439.             q->uuconf_pzlocal_send = pznew;
  440.             q->uuconf_pzlocal_receive = pznew;
  441.             q->uuconf_pzremote_send = pznew;
  442.             q->uuconf_pzremote_receive = pznew;
  443.           }
  444.  
  445.         break;
  446.           }
  447.       }
  448.  
  449.     (void) fclose (e);
  450.  
  451.     if (iret != UUCONF_SUCCESS)
  452.       {
  453.         if (zline != NULL)
  454.           free ((pointer) zline);
  455.         if (pzsplit != NULL)
  456.           free ((pointer) pzsplit);
  457.         qglobal->zfilename = qglobal->qprocess->zv2userfile;
  458.         return iret | UUCONF_ERROR_FILENAME | UUCONF_ERROR_LINENO;
  459.       }
  460.  
  461.     if (qsys->uuconf_pzlocal_send == (char **) &_uuconf_unset
  462.         && pzlocal != NULL)
  463.       {
  464.         for (q = qsys; q != NULL; q = q->uuconf_qalternate)
  465.           {
  466.         q->uuconf_fcallback = fdefault_callback;
  467.         q->uuconf_pzlocal_send = pzlocal;
  468.         q->uuconf_pzlocal_receive = pzlocal;
  469.           }
  470.       }
  471.  
  472.     if (qsys->uuconf_pzremote_send == (char **) &_uuconf_unset
  473.         && pzremote != NULL)
  474.       {
  475.         for (q = qsys; q != NULL; q = q->uuconf_qalternate)
  476.           {
  477.         q->uuconf_zcalled_login = zdefault_login;
  478.         q->uuconf_pzremote_send = pzremote;
  479.         q->uuconf_pzremote_receive = pzremote;
  480.           }
  481.       }
  482.       }
  483.   }
  484.  
  485.   /* Now we must read L.cmds to determine which commands may be
  486.      executed.  */
  487.   {
  488.     e = fopen (qglobal->qprocess->zv2cmds, "r");
  489.     if (e != NULL)
  490.       {
  491.     qglobal->ilineno = 0;
  492.  
  493.     if (getline (&zline, &cline, e) > 0)
  494.       {
  495.         ++qglobal->ilineno;
  496.  
  497.         zline[strcspn (zline, "#\n")] = '\0';
  498.         if (strncmp (zline, "PATH=", sizeof "PATH=" - 1) == 0)
  499.           {
  500.         int ctoks;
  501.         char **pznew;
  502.  
  503.         zline += sizeof "PATH=" - 1;
  504.         ctoks = _uuconf_istrsplit (zline, ':', &pzsplit, &csplit);
  505.         if (ctoks < 0)
  506.           {
  507.             qglobal->ierrno = errno;
  508.             iret = UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO;
  509.           }
  510.  
  511.         pznew = NULL;
  512.         if (iret == UUCONF_SUCCESS)
  513.           {
  514.             pznew = ((char **)
  515.                  uuconf_malloc (pblock,
  516.                          (ctoks + 1) * sizeof (char *)));
  517.             if (pznew == NULL)
  518.               iret = UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO;
  519.           }
  520.         if (iret == UUCONF_SUCCESS)
  521.           {
  522.             memcpy ((pointer) pznew, (pointer) pzsplit,
  523.                 ctoks * sizeof (char *));
  524.             pznew[ctoks] = NULL;
  525.             qsys->uuconf_pzpath = pznew;
  526.             zline = NULL;
  527.             cline = 0;
  528.           }      
  529.  
  530.         if (getline (&zline, &cline, e) < 0)
  531.           {
  532.             if (zline != NULL)
  533.               {
  534.             free ((pointer) zline);
  535.             zline = NULL;
  536.               }
  537.           }
  538.         else
  539.           ++qglobal->ilineno;
  540.           }
  541.       }
  542.  
  543.     if (iret == UUCONF_SUCCESS && zline != NULL)
  544.       {
  545.         while (TRUE)
  546.           {
  547.         zline[strcspn (zline, "#\n")] = '\0';
  548.         iret = _uuconf_iadd_string (qglobal, zline, TRUE, FALSE,
  549.                         &qsys->uuconf_pzcmds,
  550.                         pblock);
  551.         if (iret != UUCONF_SUCCESS)
  552.           break;
  553.         if (getline (&zline, &cline, e) < 0)
  554.           break;
  555.         ++qglobal->ilineno;
  556.           }
  557.       }
  558.  
  559.     (void) fclose (e);
  560.  
  561.     if (iret != UUCONF_SUCCESS)
  562.       {
  563.         qglobal->zfilename = qglobal->qprocess->zv2cmds;
  564.         iret |= UUCONF_ERROR_FILENAME | UUCONF_ERROR_LINENO;
  565.       }
  566.       }
  567.   }
  568.  
  569.   if (zline != NULL)
  570.     free ((pointer) zline);
  571.   if (pzsplit != NULL)
  572.     free ((pointer) pzsplit);
  573.  
  574.   return iret;
  575. }
  576.